package com.sz.biz.pay.transfer.service.impl;

import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.common.utils.NOGenerator;
import com.sz.biz.pay.account.entity.*;
import com.sz.biz.pay.account.service.*;
import com.sz.biz.pay.constants.PayAction;
import com.sz.biz.pay.constants.PayConstant;
import com.sz.biz.pay.transfer.service.BankCallBackServiceService;
import com.sz.biz.pay.util.BackDataUtil;
import com.sz.biz.pay.util.PayMessageTemplateUtil;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.utils.JsonUtils;
import com.sz.common.base.utils.UUIDGenerator;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.service.SysSmsService;
import com.sz.common.pay.common.DateGenerator;
import com.sz.common.pay.pingan.constant.Bank;
import com.sz.common.pay.pingan.constant.BankCodeData;
import com.sz.common.pay.pingan.constant.ResponseCode;
import com.sz.common.pay.pingan.core.server.PAServer;
import com.sz.common.pay.pingan.entity.b2b.account.OpenRemoveAccountRequest;
import com.sz.common.pay.pingan.entity.b2b.account.OpenRemoveAccountResponse;
import com.sz.common.pay.pingan.entity.b2b.rechargewithdrawal.RechargeFromBankRequest;
import com.sz.common.pay.pingan.entity.b2b.rechargewithdrawal.RechargeFromBankResponse;
import com.sz.common.pay.pingan.entity.b2b.rechargewithdrawal.WithdrawalFromBankRequest;
import com.sz.common.pay.pingan.entity.b2b.rechargewithdrawal.WithdrawalFromBankResponse;
import com.sz.common.pay.pingan.entity.b2b.transfer.BankRecheckNotifyRequest;
import com.sz.common.pay.pingan.entity.b2b.transfer.BankRecheckNotifyResponse;
import com.sz.common.pay.pingan.exception.OperationFailedException;
import com.sz.common.pay.pingan.exception.PayCommonException;
import com.sz.common.pay.pingan.util.PayExceptionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Function: 银行回调 <br>
 *
 * @author: siqishangshu <br>
 * @date: 2017-12-21 11:20:00
 */
@Service
public class BankCallBackServiceServiceImpl implements BankCallBackServiceService {

    @Autowired
    TransactionService transactionService;
    @Autowired
    AccountService accountService;
    @Autowired
    ThirdPayAccountService thirdPayAccountService;
    @Autowired
    BankCardService bankCardService;
    @Autowired
    SysSmsService sysSmsService;
    @Autowired
    BankInfoService bankInfoService;

    @Value("${pay.sms.templatecode}")
    private String smsTemplateCode;

    /**
     * 会员签解约维护【1303】
     *
     * @param sequence
     * @param tranMessage
     * @return
     * @throws OperationFailedException
     * @throws PayCommonException
     */
    @Override
    public Object handle1303(String sequence, String tranMessage) throws OperationFailedException, PayCommonException {
        OpenRemoveAccountResponse response = new OpenRemoveAccountResponse();
        OpenRemoveAccountRequest request = (OpenRemoveAccountRequest) PAServer.getRequestInfo(sequence,
                tranMessage, OpenRemoveAccountRequest.class);
        //根据银行发送的请求查找系统中的账户
        Account account = accountService.findById(request.getThirdCustId());
        if (null == account) {
            PayExceptionUtil.throwPayCommonException(sequence, ResponseCode.ERR041);
        }
        //功能标志
        String funcFlag = request.getFuncFlag();
        //签约
        if (funcFlag.equals(PayConstant.FuncFlag.SPECIFY)) {
            //修改账户信息
            account.setId(request.getThirdCustId());
            account.setIdType(request.getIdType());
            account.setIdCode(request.getIdCode());
            account.setLastUpdateTime(new Date());
            accountService.update(account);

            BankCard bankCard1 = bankCardService.getByCardNo(request.getRelatedAcctId());
            //第一次签约
            if (null == bankCard1) {
                //添加第三方账户信息
                ThirdPayAccount thirdPayAccount = new ThirdPayAccount();
                thirdPayAccount.setId(UUIDGenerator.generateRandomUUID());
                thirdPayAccount.setAccountId(request.getThirdCustId());
                thirdPayAccount.setThirdType(PayConstant.PaymentType.PINGAN);
                thirdPayAccount.setThirdPayId(request.getCustAcctId());
                thirdPayAccount.setThirdPayName(request.getCustName());
                thirdPayAccount.setCurrency(PayConstant.Currency.RMB);
                thirdPayAccountService.insertSelective(thirdPayAccount);
                //添加银行卡信息
                BankCard bankCard = new BankCard();
                bankCard.setCardNo(request.getRelatedAcctId());
                bankCard.setMobile(account.getMobilePhone());
                bankCard.setCurrency(PayConstant.Currency.RMB);
                bankCard.setsBankCode(request.getBankCode());
                BankInfo bankInfo = bankInfoService.select(request.getBankCode());
                Bank bank = (Bank) BankCodeData.getBanksByCode(bankInfo.getBankClsCode()).get(0);
                bankCard.setBank(bank.getName());
                bankCard.setSubbranch(request.getBankName());
                bankCard.setIdType(request.getIdType());
                bankCard.setIdCode(request.getIdCode());
                bankCard.setThirdPayAccountId(thirdPayAccount.getId());
                bankCard.setId(UUIDGenerator.generateRandomUUID());
                bankCard.setHolder(request.getCustName());
                bankCardService.insertSelective(bankCard);
            } else {
                //修改第三方账户删除标记
                ThirdPayAccount thirdPayAccount = thirdPayAccountService.getByAccountIdAndThirdType(
                        request.getThirdCustId(), PayConstant.PaymentType.PINGAN);
                thirdPayAccount.setAccountId(request.getThirdCustId());
                thirdPayAccount.setThirdPayId(request.getCustAcctId());
                thirdPayAccount.setThirdPayName(request.getCustName());
                thirdPayAccount.setIsDeleted(false);
                thirdPayAccountService.update(thirdPayAccount);
                //修改银行卡删除标记
                bankCard1.setCardNo(request.getRelatedAcctId());
                bankCard1.setsBankCode(request.getBankCode());
                BankInfo bankInfo = bankInfoService.select(request.getBankCode());
                Bank bank = (Bank) BankCodeData.getBanksByCode(bankInfo.getBankClsCode()).get(0);
                bankCard1.setBank(bank.getName());
                bankCard1.setSubbranch(request.getBankName());
                bankCard1.setIdType(request.getIdType());
                bankCard1.setIdCode(request.getIdCode());
                bankCard1.setHolder(request.getCustName());

                bankCard1.setIsDeleted(false);
                bankCard1.setLastUpdateTime(new Date());
                bankCardService.update(bankCard1);
            }
            Map<String, Object> smsBodyMap = new HashMap<>();
            smsBodyMap.put("accountStatus","Signing");
            String smsBody = JsonUtils.toJSONString(smsBodyMap);
            sysSmsService.createSMS(account.getMobilePhone(), smsBody, smsTemplateCode);

        } else if (funcFlag.equals(PayConstant.FuncFlag.MODIFY)) {
            //修改账户信息
            account.setId(request.getThirdCustId());
            account.setIdType(request.getIdType());
            account.setIdCode(request.getIdCode());
            account.setLastUpdateTime(new Date());
            accountService.update(account);
            //修改第三方账户信息
            ThirdPayAccount thirdPayAccount = thirdPayAccountService.getByAccountIdAndThirdType(
                    request.getThirdCustId(), PayConstant.PaymentType.PINGAN);
            thirdPayAccount.setAccountId(request.getThirdCustId());
            thirdPayAccount.setThirdPayId(request.getCustAcctId());
            thirdPayAccount.setThirdPayName(request.getCustName());
            thirdPayAccountService.update(thirdPayAccount);
            //修改银行卡信息
            BankCard bankCard = bankCardService.getByCardNo(request.getOldRelatedAcctId());
            bankCard.setCardNo(request.getRelatedAcctId());
            bankCard.setsBankCode(request.getBankCode());
            BankInfo bankInfo = bankInfoService.select(request.getBankCode());
            Bank bank = (Bank) BankCodeData.getBanksByCode(bankInfo.getBankClsCode()).get(0);
            bankCard.setBank(bank.getName());
            bankCard.setSubbranch(request.getBankName());
            bankCard.setIdType(request.getIdType());
            bankCard.setIdCode(request.getIdCode());
            bankCard.setHolder(request.getCustName());
            bankCard.setLastUpdateTime(new Date());
            bankCardService.update(bankCard);
            sysSmsService.createSMS(account.getMobilePhone(), "", smsTemplateCode);
        } else if (funcFlag.equals(PayConstant.FuncFlag.DEL)) {
            //修改第三方账户删除标记
            ThirdPayAccount thirdPayAccount = thirdPayAccountService.getByAccountIdAndThirdType(request.getThirdCustId(), PayConstant.PaymentType.PINGAN);
            thirdPayAccount.setIsDeleted(true);
            thirdPayAccountService.update(thirdPayAccount);
            //修改银行卡删除标记
            BankCard bankCard = bankCardService.getByCardNo(request.getRelatedAcctId());
            bankCard.setIsDeleted(true);
            bankCard.setLastUpdateTime(new Date());
            bankCardService.update(bankCard);
            sysSmsService.createSMS(account.getMobilePhone(), "", smsTemplateCode);
        } else {
            PayExceptionUtil.throwPayCommonException(sequence, ResponseCode.ERR021);
        }
        response.setThirdLogNo(sequence);
        response.setReserve("signSuccess");
        return response;
    }

    /**
     * 入金（银行发起）【1310】
     *
     * @param thirdLogNo
     * @param tranMessage
     * @return
     * @throws OperationFailedException
     * @throws PayCommonException
     */
    @Override
    public Object handle1310(String thirdLogNo, String tranMessage)
            throws OperationFailedException, PayCommonException {
        RechargeFromBankResponse response = new RechargeFromBankResponse();

        RechargeFromBankRequest request = (RechargeFromBankRequest) PAServer.getRequestInfo(thirdLogNo, tranMessage, RechargeFromBankRequest.class);
        ThirdPayAccount thirdPayAccount = thirdPayAccountService.findByCustAcctId(request.getCustAcctId());

        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.REQUEST, PayAction.RECHARGE,
                BackDataUtil.makeMap(thirdLogNo, request));
        rechargeTransaction(thirdLogNo, request, thirdPayAccount);
        response.setThirdLogNo(thirdLogNo);
        response.setReserve(request.getReserve());
        return response;
    }

    private Transaction rechargeTransaction(String thirdLogNo, RechargeFromBankRequest depositRequest, ThirdPayAccount thirdPayAccount) {
        Transaction transaction = new Transaction();
        transaction.setId(NOGenerator.getTranNo(PayConstant.TranscationType.RECHARGE));
        transaction.setThirdLogNo(thirdLogNo);
        transaction.setTranStatus(PayConstant.TranStatus.SUCCESS);
        transaction.setCreateTime(new Date());
        transaction.setTranType(PayConstant.TranscationType.RECHARGE);
        transaction.setThirdType(PayConstant.PaymentType.PINGAN);
        transaction.setNote(depositRequest.getReserve());
        transaction.setCreateUserId(PrincipalUtils.getAccountId());
        transaction.setCurrency(depositRequest.getCcyCode());
        transaction.setHandFee(0.0);
        transaction.setTranAmount(Double.parseDouble(depositRequest.getTranAmount()));
        Account account = accountService.select(thirdPayAccount.getAccountId());

        transaction.setOutAccountId(depositRequest.getInAcctId());
        transaction.setOutAccountName(depositRequest.getInAcctIdName());

        transaction.setInAccountBalance(
                bankCardService.getAccountBalance(thirdPayAccount.getThirdPayId()));
        transaction.setInAccountId(account.getId());
        transaction.setInAccountName(account.getCustName());
        transaction.setInThirdPayAccountId(thirdPayAccount.getThirdPayId());
        transaction.setInThirdPayAccountName(thirdPayAccount.getThirdPayName());
        transaction.setIsDeleted(false);
        transaction.setTranDate(DateGenerator.getyyyyMMdd());
        transaction.setTranTime(DateGenerator.getHHmmss());
        transactionService.insert(transaction);
        sysSmsService.createSMS(account.getMobilePhone(), PayMessageTemplateUtil.makeMessage(transaction), smsTemplateCode);
        return transaction;
    }

    /**
     * 出金（银行发起）【1312】
     *
     * @param thirdLogNo
     * @param tranMessage
     * @return
     * @throws OperationFailedException
     * @throws PayCommonException
     */
    @Override
    public Object handle1312(String thirdLogNo, String tranMessage) throws OperationFailedException, PayCommonException {
        WithdrawalFromBankResponse response = new WithdrawalFromBankResponse();
        WithdrawalFromBankRequest request = (WithdrawalFromBankRequest) PAServer.getRequestInfo(thirdLogNo, tranMessage, WithdrawalFromBankRequest.class);
        withdrawalsTranscation(thirdLogNo, request);
        response.setThirdLogNo(thirdLogNo);
        response.setReserve(request.getReserve());
        //TODO
        if (PayConstant.NEED_CONFIRMED) {
            PayExceptionUtil.throwPayCommonException("Withdrawal From Bank Need Confirmed", ResponseCode.NO_RECORD);
        }
        return response;
    }

    private Transaction withdrawalsTranscation(String thirdLogNo, WithdrawalFromBankRequest withdrawalFromBankRequest) {
        Transaction transaction = new Transaction();
        transaction.setId(NOGenerator.getTranNo(PayConstant.TranscationType.WITHDRAWAL));
        transaction.setThirdLogNo(thirdLogNo);
        transaction.setTranStatus(PayConstant.TranStatus.NEED_CONFIRMED);
        transaction.setCreateTime(new Date());
        transaction.setCreateUserId(PrincipalUtils.getAccountId());
        transaction.setCurrency(withdrawalFromBankRequest.getCcyCode());
        transaction.setHandFee(Double.parseDouble(withdrawalFromBankRequest.getHandFee()));
        transaction.setTranAmount(Double.parseDouble(withdrawalFromBankRequest.getTranAmount()));

        Account account = accountService.select(withdrawalFromBankRequest.getThirdCustId());
        if (account != null) {
            transaction.setOutAccountId(account.getId());
            transaction.setOutAccountName(account.getCustName());
        }
        transaction.setOutAccountBalance(
                bankCardService.getAccountBalance(withdrawalFromBankRequest.getCustAcctId()));

        ThirdPayAccount thirdPayAccount = thirdPayAccountService.findByCustAcctId(withdrawalFromBankRequest.getCustAcctId());
        if (thirdPayAccount != null) {
            transaction.setOutThirdPayAccountId(thirdPayAccount.getThirdPayId());
            transaction.setOutThirdPayAccountName(thirdPayAccount.getThirdPayName());
        }
        transaction.setTranType(PayConstant.TranscationType.WITHDRAWAL);
        transaction.setThirdType(PayConstant.PaymentType.PINGAN);
        transaction.setNote(withdrawalFromBankRequest.getReserve());

        transaction.setInAccountId(withdrawalFromBankRequest.getOutAcctId());
        transaction.setInAccountName(withdrawalFromBankRequest.getOutAcctIdName());
        transaction.setIsDeleted(false);
        transaction.setTranDate(DateGenerator.getyyyyMMdd());
        transaction.setTranTime(DateGenerator.getHHmmss());
        transactionService.insert(transaction);
        sysSmsService.createSMS(account.getMobilePhone(), PayMessageTemplateUtil.makeMessage(transaction), smsTemplateCode);
        return transaction;
    }

    /**
     * 银行复核通知【1326】
     *
     * @param sequence
     * @param tranMessage
     * @return
     * @throws OperationFailedException
     * @throws PayCommonException
     */
    @Override
    public Object handle1326(String sequence, String tranMessage) throws OperationFailedException, PayCommonException {
        BankRecheckNotifyResponse response = new BankRecheckNotifyResponse();
        BankRecheckNotifyRequest request = (BankRecheckNotifyRequest) PAServer.getRequestInfo(sequence, tranMessage, BankRecheckNotifyRequest.class);

        response.setThirdLogNo(sequence);

        Transaction transaction = transactionService.findByThirdLogNo(request.getPaySerialNo());
        if (null != transaction) {
            response.setThirdLogNo(transaction.getThirdLogNo());
            if (request.getCheckResult().equals(PayConstant.RecheckFlag.PASSED)) {
                transaction.setTranStatus(PayConstant.TranStatus.SUCCESS);
                transactionService.update(transaction);
                PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.REQUEST, PayAction.PAY,
                        BackDataUtil.makeMap(transaction.getThirdLogNo(), request));
            }
        }
        return response;
    }
}
